#include "bluetooth_serial.h"
#include <Arduino.h>

// 蓝牙串口实现
BluetoothSerial::BluetoothSerial() : pServer(nullptr), pTxCharacteristic(nullptr), 
                                     pRxCharacteristic(nullptr), deviceConnected(false),
                                     rxBufferHead(0), rxBufferTail(0) {
    // 初始化接收缓冲区
    memset(rxBuffer, 0, RX_BUFFER_SIZE);
}

BluetoothSerial::~BluetoothSerial() {
    // 清理资源
    if (pServer) {
        BLEDevice::stopAdvertising();
        delete pServer;
        pServer = nullptr;
    }
}

void BluetoothSerial::begin(const char* deviceName) {
    // 初始化BLE设备
    BLEDevice::init(deviceName);
    
    // 创建BLE服务器
    pServer = BLEDevice::createServer();
    // 创建匿名回调类实例
    class ServerCallbacks : public BLEServerCallbacks {
        BluetoothSerial* parent;
    public:
        ServerCallbacks(BluetoothSerial* p) : parent(p) {}
        void onConnect(BLEServer* pServer) {
            parent->deviceConnected = true;
        }
        
        void onDisconnect(BLEServer* pServer) {
            parent->deviceConnected = false;
            // 重新启动广播以允许重新连接
            BLEDevice::startAdvertising();
        }
    };
    
    pServer->setCallbacks(new ServerCallbacks(this));
    
    // 创建BLE服务
    BLEService* pService = pServer->createService(SERVICE_UUID);
    
    // 创建接收特征（写入）
    pRxCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID_RX,
        BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_WRITE_NR
    );
    // 创建匿名回调类实例
    class RxCallbacks : public BLECharacteristicCallbacks {
        BluetoothSerial* parent;
    public:
        RxCallbacks(BluetoothSerial* p) : parent(p) {}
        void onWrite(BLECharacteristic* pCharacteristic) {
            std::string rxValue = pCharacteristic->getValue();
            
            if (rxValue.length() > 0) {
                for (int i = 0; i < rxValue.length(); i++) {
                    // 将接收到的数据放入缓冲区
                    int nextHead = (parent->rxBufferHead + 1) % parent->RX_BUFFER_SIZE;
                    if (nextHead != parent->rxBufferTail) {
                        parent->rxBuffer[parent->rxBufferHead] = rxValue[i];
                        parent->rxBufferHead = nextHead;
                    }
                }
            }
        }
    };
    
    pRxCharacteristic->setCallbacks(new RxCallbacks(this));
    
    // 创建发送特征（通知）
    pTxCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID_TX,
        BLECharacteristic::PROPERTY_NOTIFY
    );
    pTxCharacteristic->addDescriptor(new BLE2902());
    
    // 启动服务
    pService->start();
    
    // 启动广播
    BLEAdvertising* pAdvertising = BLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(SERVICE_UUID);
    pAdvertising->setScanResponse(true);
    pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
    pAdvertising->setMinPreferred(0x12);
    BLEDevice::startAdvertising();
}

bool BluetoothSerial::available() {
    return (rxBufferHead != rxBufferTail);
}

uint8_t BluetoothSerial::read() {
    if (rxBufferHead == rxBufferTail) {
        return 0;
    }
    
    uint8_t data = rxBuffer[rxBufferTail];
    rxBufferTail = (rxBufferTail + 1) % RX_BUFFER_SIZE;
    return data;
}

void BluetoothSerial::write(uint8_t data) {
    if (deviceConnected) {
        pTxCharacteristic->setValue(&data, 1);
        pTxCharacteristic->notify();
    }
}

void BluetoothSerial::write(const uint8_t* data, size_t length) {
    if (deviceConnected && length > 0) {
        pTxCharacteristic->setValue(const_cast<uint8_t*>(data), length);
        pTxCharacteristic->notify();
    }
}

void BluetoothSerial::print(const char* data) {
    if (deviceConnected && data) {
        size_t length = strlen(data);
        pTxCharacteristic->setValue((uint8_t*)data, length);
        pTxCharacteristic->notify();
    }
}

void BluetoothSerial::println(const char* data) {
    if (deviceConnected && data) {
        size_t length = strlen(data);
        uint8_t* newData = new uint8_t[length + 2];
        strcpy((char*)newData, data);
        strcat((char*)newData, "\n");
        pTxCharacteristic->setValue(newData, length + 1);
        pTxCharacteristic->notify();
        delete[] newData;
    }
}

bool BluetoothSerial::isConnected() {
    return deviceConnected;
}